package com.smh.demo1.a04;

import org.springframework.beans.PropertyValue;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.annotation.InjectionMetadata;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ContextAnnotationAutowireCandidateResolver;
import org.springframework.core.MethodParameter;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.util.StringValueResolver;

import javax.management.StandardEmitterMBean;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @author shiminghui
 * @date 2025/4/11 11:01
 * @description: TODO
 */
public class TestAutowiredPostProcessor {
    public static void main(String[] args) throws Throwable {

        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver()); //处理@value字段值的注入
        beanFactory.addEmbeddedValueResolver(strVal -> new StandardEnvironment().resolvePlaceholders(strVal)); //添加一个${} 的解析器

        beanFactory.registerSingleton("bean2", new Bean2());
        beanFactory.registerSingleton("bean3", new Bean3());

        AutowiredAnnotationBeanPostProcessor postProcessor = new AutowiredAnnotationBeanPostProcessor();
        postProcessor.setBeanFactory(beanFactory); // postProcessor需要依赖beanFactory中的一些信息,可能包括一些bean

        Bean1 bean1 = new Bean1();
//        postProcessor.postProcessProperties(null, bean1, "bean1"); // 执行依赖注入,解析autowired
//
//        System.out.println(bean1);

        // ---------------------------------------------------------------- //

        // postProcessProperties 其实就是调用了findAutowiringMetadata找到注解信息(InjectionMetadata), 然后调用InjectionMetadata的inject方法进行注入
        Method findAutowiringMetadata = AutowiredAnnotationBeanPostProcessor.class.getDeclaredMethod("findAutowiringMetadata", String.class, Class.class, PropertyValues.class);
        findAutowiringMetadata.setAccessible(true);

        // 获取bean1类里面Autowired 和 value 的注解信息
        InjectionMetadata metadata = (InjectionMetadata) findAutowiringMetadata.invoke(postProcessor, "bean1", Bean1.class, null);
        System.out.println(metadata);

        // 进行依赖注入
//        metadata.inject(bean1, "bean1", null);
//        System.out.println(bean1);


        // inject 的内部执行流程
        //(成员变量)
        Field bean3 = Bean1.class.getDeclaredField("bean3");
        DependencyDescriptor dd1 = new DependencyDescriptor(bean3, false);
        Object o = beanFactory.resolveDependency(dd1, null, null, null);// 通过字段值可以确定字段类型,然后根据类型去BeanFactory去查找bean进行注入
        System.out.println(o);
        // 之后通过反射设置值

        // (set方法)
        Method setBean3 = Bean1.class.getDeclaredMethod("setBean3", Bean3.class);
        DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean3, 0), false);
        Object o1 = beanFactory.resolveDependency(dd2, null, null, null);
        System.out.println(o1);
        // 之后通过反射调用set方法进行注入

        // (值注入)
        Method setProperties = Bean1.class.getDeclaredMethod("setProperties", String.class);
        DependencyDescriptor dd3 = new DependencyDescriptor(new MethodParameter(setProperties, 0), false);
        Object o2 = beanFactory.resolveDependency(dd3, null, null, null);
        System.out.println(o2);
        // 之后通过反射调用set方法进行注入,注,这里都没有完成注入,只是解析到了要注入的bean

        System.out.println(bean1);
    }
}
